<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="深入理解java虚拟机,">










<meta name="description" content="创建型模式：对象实例化的模式，创建型模式用于解耦对象的实例化过程。 结构型模式：把类或对象结合在一起形成一个更大的结构。 行为型模式：类和对象如何交互，及划分责任和算法。 二、设计模式的六大原则总原则：开闭原则（Open Close Principle）开闭原则就是说对扩展开放，对修改关闭。在程序需要进行拓展的时候，不能去修改原有的代码，而是要扩展原有代码，实现一个热插拔的效果。所以一句话概括">
<meta name="keywords" content="深入理解java虚拟机">
<meta property="og:type" content="article">
<meta property="og:title" content="设计模式">
<meta property="og:url" content="https://blog.xiezc.xyz/2019/01/28/设计模式/index.html">
<meta property="og:site_name" content="xiezc的小站">
<meta property="og:description" content="创建型模式：对象实例化的模式，创建型模式用于解耦对象的实例化过程。 结构型模式：把类或对象结合在一起形成一个更大的结构。 行为型模式：类和对象如何交互，及划分责任和算法。 二、设计模式的六大原则总原则：开闭原则（Open Close Principle）开闭原则就是说对扩展开放，对修改关闭。在程序需要进行拓展的时候，不能去修改原有的代码，而是要扩展原有代码，实现一个热插拔的效果。所以一句话概括">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://images2017.cnblogs.com/blog/401339/201709/401339-20170928225241215-295252070.png">
<meta property="og:image" content="https://images2017.cnblogs.com/blog/401339/201709/401339-20170929202530606-709085396.png">
<meta property="og:image" content="https://images2017.cnblogs.com/blog/401339/201709/401339-20170929204041684-1520979160.png">
<meta property="og:image" content="https://images2017.cnblogs.com/blog/401339/201709/401339-20170929204151184-2094793629.png">
<meta property="og:image" content="https://images2017.cnblogs.com/blog/401339/201709/401339-20170929204518044-666328371.png">
<meta property="og:image" content="https://images2017.cnblogs.com/blog/401339/201709/401339-20170929205441153-1950745368.png">
<meta property="og:updated_time" content="2019-04-04T14:42:39.406Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="设计模式">
<meta name="twitter:description" content="创建型模式：对象实例化的模式，创建型模式用于解耦对象的实例化过程。 结构型模式：把类或对象结合在一起形成一个更大的结构。 行为型模式：类和对象如何交互，及划分责任和算法。 二、设计模式的六大原则总原则：开闭原则（Open Close Principle）开闭原则就是说对扩展开放，对修改关闭。在程序需要进行拓展的时候，不能去修改原有的代码，而是要扩展原有代码，实现一个热插拔的效果。所以一句话概括">
<meta name="twitter:image" content="https://images2017.cnblogs.com/blog/401339/201709/401339-20170928225241215-295252070.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://blog.xiezc.xyz/2019/01/28/设计模式/">





  <title>设计模式 | xiezc的小站</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?8ae02d8cf311eabbae2621ff2d51a260";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">xiezc的小站</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">xiezc的小站</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://blog.xiezc.xyz/2019/01/28/设计模式/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="xiezc">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="xiezc的小站">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">设计模式</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-01-28T10:29:15+08:00">
                2019-01-28
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/java/" itemprop="url" rel="index">
                    <span itemprop="name">java</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          
             <span id="/2019/01/28/设计模式/" class="leancloud_visitors" data-flag-title="设计模式">
               <span class="post-meta-divider">|</span>
               <span class="post-meta-item-icon">
                 <i class="fa fa-eye"></i>
               </span>
               
                 <span class="post-meta-item-text">阅读次数&#58;</span>
               
                 <span class="leancloud-visitors-count"></span>
             </span>
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p><img src="https://images2017.cnblogs.com/blog/401339/201709/401339-20170928225241215-295252070.png" alt="img"> </p>
<p><strong>创建型模式：对象实例化的模式，创建型模式用于解耦对象的实例化过程。</strong></p>
<p><strong>结构型模式：把类或对象结合在一起形成一个更大的结构。</strong></p>
<p><strong>行为型模式：类和对象如何交互，及划分责任和算法。</strong></p>
<h2 id="二、设计模式的六大原则"><a href="#二、设计模式的六大原则" class="headerlink" title="二、设计模式的六大原则"></a>二、设计模式的六大原则</h2><h3 id="总原则：开闭原则（Open-Close-Principle）"><a href="#总原则：开闭原则（Open-Close-Principle）" class="headerlink" title="总原则：开闭原则（Open Close Principle）"></a>总原则：开闭原则（Open Close Principle）</h3><p>开闭原则就是说<strong>对扩展开放，对修改关闭</strong>。在程序需要进行拓展的时候，不能去修改原有的代码，而是要扩展原有代码，实现一个热插拔的效果。所以一句话概括就是：为了使程序的扩展性好，易于维护和升级。想要达到这样的效果，我们需要使用接口和抽象类等，后面的具体设计中我们会提到这点。</p>
<h3 id="1、单一职责原则"><a href="#1、单一职责原则" class="headerlink" title="1、单一职责原则"></a>1、单一职责原则</h3><p>不要存在多于一个导致类变更的原因，也就是说每个类应该实现单一的职责，如若不然，就应该把类拆分。</p>
<h3 id="2、里氏替换原则（Liskov-Substitution-Principle）"><a href="#2、里氏替换原则（Liskov-Substitution-Principle）" class="headerlink" title="2、里氏替换原则（Liskov Substitution Principle）"></a>2、里氏替换原则（Liskov Substitution Principle）</h3><p>里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说，任何基类可以出现的地方，子类一定可以出现。 LSP是继承复用的基石，只有当衍生类可以替换掉基类，软件单位的功能不受到影响时，基类才能真正被复用，而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现，所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科</p>
<p>历史替换原则中，子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构，通过这个规范的接口与外界交互，子类不应该随便破坏它。</p>
<h3 id="3、依赖倒转原则（Dependence-Inversion-Principle）"><a href="#3、依赖倒转原则（Dependence-Inversion-Principle）" class="headerlink" title="3、依赖倒转原则（Dependence Inversion Principle）"></a>3、依赖倒转原则（Dependence Inversion Principle）</h3><p>这个是开闭原则的基础，具体内容：面向接口编程，依赖于抽象而不依赖于具体。写代码时用到具体类时，不与具体类交互，而与具体类的上层接口交互。\</p>
<blockquote>
<p>Spring的ioc就是典型的这个原则</p>
</blockquote>
<h3 id="4、接口隔离原则（Interface-Segregation-Principle）"><a href="#4、接口隔离原则（Interface-Segregation-Principle）" class="headerlink" title="4、接口隔离原则（Interface Segregation Principle）"></a>4、接口隔离原则（Interface Segregation Principle）</h3><p>这个原则的意思是：每个接口中不存在子类用不到却必须实现的方法，如果不然，就要将接口拆分。使用多个隔离的接口，比使用单个接口（多个接口方法集合到一个的接口）要好。</p>
<blockquote>
<p>接口必须精简拆分</p>
</blockquote>
<h3 id="5、迪米特法则（最少知道原则）（Demeter-Principle）"><a href="#5、迪米特法则（最少知道原则）（Demeter-Principle）" class="headerlink" title="5、迪米特法则（最少知道原则）（Demeter Principle）"></a>5、迪米特法则（最少知道原则）（Demeter Principle）</h3><p>就是说：一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂，都应该将逻辑封装在方法的内部，通过public方法提供给外部。这样当被依赖的类变化时，才能最小的影响该类。</p>
<p>最少知道原则的另一个表达方式是：只与直接的朋友通信。类之间只要有耦合关系，就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。</p>
<blockquote>
<p>DO类的get和set方法就是典型的最少知道原则, 将字段定义成私有, 通过共用的方法访问</p>
</blockquote>
<h3 id="6、合成复用原则（Composite-Reuse-Principle）"><a href="#6、合成复用原则（Composite-Reuse-Principle）" class="headerlink" title="6、合成复用原则（Composite Reuse Principle）"></a>6、合成复用原则（Composite Reuse Principle）</h3><p>原则是尽量首先使用合成/聚合的方式，而不是使用继承。</p>
<h2 id="该23种设计模式"><a href="#该23种设计模式" class="headerlink" title="该23种设计模式"></a>该23种设计模式</h2><h3 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h3><p>单例模式，它的定义就是确保某一个类只有一个实例，并且提供一个全局访问点。</p>
<p>单例模式具备典型的3个特点：</p>
<ol>
<li>只有一个实例。 </li>
<li>自我实例化。</li>
<li>提供全局访问点。</li>
</ol>
<p>因此当系统中只需要一个实例对象或者系统中只允许一个公共访问点，除了这个公共访问点外，不能通过其他访问点访问该实例时，可以使用单例模式。</p>
<p>单例模式的主要优点就是节约系统资源、提高了系统效率，同时也能够严格控制客户对它的访问。也许就是因为系统中只有一个实例，这样就导致了单例类的职责过重，违背了“单一职责原则”，同时也没有抽象类，所以扩展起来有一定的困难。其UML结构图非常简单，就只有一个类，如下图：</p>
<p><img src="https://images2017.cnblogs.com/blog/401339/201709/401339-20170929202530606-709085396.png" alt="img"> </p>
<blockquote>
<p>java中实现方式是, 使用私有的构造方法, 类的私有构造方法只能被自己的静态方法调通,  而静态方法又是类所属的, 全局唯一的, 因此只需要在静态方法中判断下是否已经存在实例化的单例, 有则返回, 无则新建后返回</p>
<p>需要注意的是要考虑到单例模式的静态方法的并发处理, 因为程序中其他地方可能会随时调用这个方法</p>
</blockquote>
<h3 id="工厂方法模式"><a href="#工厂方法模式" class="headerlink" title="工厂方法模式"></a>工厂方法模式</h3><p>作为抽象工厂模式的孪生兄弟，工厂方法模式定义了一个创建对象的接口，但由子类决定要实例化的类是哪一个，也就是说工厂方法模式让实例化推迟到子类。</p>
<p>工厂方法模式非常符合“开闭原则”，当需要增加一个新的产品时，我们只需要增加一个具体的产品类和与之对应的具体工厂即可，无须修改原有系统。同时在工厂方法模式中用户只需要知道生产产品的具体工厂即可，无须关系产品的创建过程，甚至连具体的产品类名称都不需要知道。虽然他很好的符合了“开闭原则”，但是由于每新增一个新产品时就需要增加两个类，这样势必会导致系统的复杂度增加。其UML结构图：</p>
<p><img src="https://images2017.cnblogs.com/blog/401339/201709/401339-20170929204041684-1520979160.png" alt="img"></p>
<blockquote>
<p>需要为每一个产品新建一个工厂类,   有点繁琐,  因为有些类在初始化的时候还需要进行很复杂的操作, 或者很有可能逻辑还会变化,   因此把这部分复杂又已变化的部分提取出来组成工厂方法模式</p>
</blockquote>
<h3 id="抽象工厂模式"><a href="#抽象工厂模式" class="headerlink" title="抽象工厂模式"></a>抽象工厂模式</h3><p>所谓抽象工厂模式就是提供一个接口，用于创建相关或者依赖对象的家族，而不需要明确指定具体类。他允许客户端使用抽象的接口来创建一组相关的产品，而不需要关系实际产出的具体产品是什么。这样一来，客户就可以从具体的产品中被解耦。它的优点是隔离了具体类的生成，使得客户端不需要知道什么被创建了，而缺点就在于新增新的行为会比较麻烦，因为当添加一个新的产品对象时，需要更加需要更改接口及其下所有子类。其UML结构图如下：</p>
<p> <img src="https://images2017.cnblogs.com/blog/401339/201709/401339-20170929204151184-2094793629.png" alt="img"></p>
<blockquote>
<p>允许使用抽象的接口来创建一组相关产品，而不需要知道或关心实际生产出的具体产品是什么，这样就可以从具体产品中被解耦 . 因为工厂模式中需要创建许多的工厂和产品,  如果把这个工厂和产品的共有方法抽象出来,   项目中只是使用这些抽象方法, 这样就是实现了对具体产品和工厂的屏蔽,  松耦合了</p>
<p>这个模式的使用限制是, 项目只对这一系列产品的共有属性感兴趣,  所以可以把这一系列的产品提取出共有的抽象父类. </p>
</blockquote>
<p>比如: 电视机有不同的品牌,  三星, 小米, 海尔. </p>
<p>程序中只是使用电视机, 对品牌不感兴趣, 所以可以提取一个共有的父类电视机.  </p>
<p>不同的品牌的电视机都有各自品牌的电视机工厂. 所以可以提取一个共有的电视机工厂. </p>
<p>共有电视机工厂的建造方法可以根据传入的品牌生成不同的品牌的电视机,  但是这个建造方法的返回值是共有电视机. 程序中也只是使用共有电视机类,  </p>
<p>这样就实现了电视机对不同品牌的屏蔽, 工厂方法也十分简洁,  </p>
<h3 id="建造者模式"><a href="#建造者模式" class="headerlink" title="建造者模式"></a>建造者模式</h3><p>对于建造者模式而已，它主要是将一个复杂对象的构建与表示分离，使得同样的构建过程可以创建不同的表示。适用于那些产品对象的内部结构比较复杂。</p>
<p>建造者模式将复杂产品的构建过程封装分解在不同的方法中，使得创建过程非常清晰，能够让我们更加精确的控制复杂产品对象的创建过程，同时它隔离了复杂产品对象的创建和使用，使得相同的创建过程能够创建不同的产品。但是如果某个产品的内部结构过于复杂，将会导致整个系统变得非常庞大，不利于控制，同时若几个产品之间存在较大的差异，则不适用建造者模式，毕竟这个世界上存在相同点大的两个产品并不是很多，所以它的使用范围有限。其UML结构图：</p>
<p><img src="https://images2017.cnblogs.com/blog/401339/201709/401339-20170929204518044-666328371.png" alt="img"></p>
<blockquote>
<p>如果一个对象创建需要传入很多的构造参数. 并且每个参数都有复杂的逻辑, 比如非空判断, 其他处理等.  这样就会显得构造方法过于复杂.   因此可以单独建造一个类(可以是单例 ), 这个类中许多的方法专门用来处理之前的传入的构造参数, 最后构造参数处理好了后, 再调用下建造方法创建具体的对象. 就是把复杂的构造方法拆分开形成一个专门处理这些逻辑的类, </p>
<p>将对象的本身业务逻辑和对象的创建过程分离开来, 松开耦合. </p>
<p>java中典型 okHttp类库使用了大量的这个模式,  lombok 可以使用注解很方便的生成这种模式类</p>
</blockquote>
<p>优点</p>
<ul>
<li>易于解耦<br> 将产品本身与产品创建过程进行解耦，可以使用相同的创建过程来得到不同的产品。也就说细节依赖抽象。</li>
<li>易于精确控制对象的创建<br> 将复杂产品的创建步骤分解在不同的方法中，使得创建过程更加清晰</li>
<li>易于拓展<br> 增加新的具体建造者无需修改原有类库的代码，易于拓展，符合“开闭原则“。</li>
</ul>
<blockquote>
<p>每一个具体建造者都相对独立，而与其他的具体建造者无关，因此可以很方便地替换具体建造者或增加新的具体建造者，用户使用不同的具体建造者即可得到不同的产品对象。</p>
</blockquote>
<p> 缺点</p>
<ul>
<li>建造者模式所创建的产品一般具有较多的共同点，其组成部分相似；如果产品之间的差异性很大，则不适合使用建造者模式，因此其使用范围受到一定的限制。</li>
<li>如果产品的内部变化复杂，可能会导致需要定义很多具体建造者类来实现这种变化，导致系统变得很庞大。</li>
</ul>
<h3 id="原型模式"><a href="#原型模式" class="headerlink" title="原型模式"></a>原型模式</h3><p>原型模式（Prototype Pattern）是用于创建重复的对象，同时又能保证性能。这种类型的设计模式属于创建型模式，它提供了一种创建对象的最佳方式。 </p>
<p>在我们应用程序可能有某些对象的结构比较复杂，但是我们又需要频繁的使用它们，如果这个时候我们来不断的新建这个对象势必会大大损耗系统内存的，这个时候我们需要使用原型模式来对这个结构复杂又要频繁使用的对象进行克隆。所以原型模式就是用原型实例指定创建对象的种类，并且通过复制这些原型创建新的对象。</p>
<p>它主要应用与那些创建新对象的成本过大时。它的主要优点就是简化了新对象的创建过程，提高了效率，同时原型模式提供了简化的创建结构。UML结构图：</p>
<p><img src="https://images2017.cnblogs.com/blog/401339/201709/401339-20170929205441153-1950745368.png" alt="img"></p>
<p><strong>模式结构</strong><br>原型模式包含如下角色：<br>Prototype：抽象原型类<br>ConcretePrototype：具体原型类<br>Client：客户类</p>
<blockquote>
<p>原型模式就是实现clone 接口用来生成新的对象, 而不用每次生成对象的都调用复杂的对象初始化逻辑</p>
<p>这个模式 感觉是一个鸡肋模式.   </p>
</blockquote>
<h1 id="适配器模式"><a href="#适配器模式" class="headerlink" title="适配器模式"></a>适配器模式</h1><p>适配器模式（Adapter Pattern）是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式，它结合了两个独立接口的功能。</p>
<p>这种模式涉及到一个单一的类，该类负责加入独立的或不兼容的接口功能。举个真实的例子，读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器，再将读卡器插入笔记本，这样就可以通过笔记本来读取内存卡。</p>
<blockquote>
<p>适配器模式 也可以理解为屏蔽不同类型的产品.  使得系统可以使用统一的方法来调用不同产品的功能</p>
<p>java的awt桌面编程中用到了许多的适配器模式.  以后的项目中如果要加入第三方的依赖的时候, 建议使用适配器屏蔽下第三方的依赖具体调用, 这样如果第三方依赖换了的时候, 我们只需要修改下适配器类的实现就可以继续运行项目了. </p>
</blockquote>
<h1 id="桥接模式"><a href="#桥接模式" class="headerlink" title="桥接模式"></a>桥接模式</h1><p>桥接（Bridge）是用于把抽象化与实现化解耦，使得二者可以独立变化。这种类型的设计模式属于结构型模式，它通过提供抽象化和实现化之间的桥接结构，来实现二者的解耦。</p>
<p>这种模式涉及到一个作为桥接的接口，使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。</p>
<blockquote>
<p>实现类需要实现接口, 直接实现就会把接口和实现类耦合太紧了, 所以在实现类和接口中间加上一个抽象类, 抽象类去实现接口, 实现类再去集成抽象类</p>
<p>简直是无所不用其极, 本来使用接口和实现类就是一种松耦合.  为了更加的松耦合, 还加上抽象层,</p>
<p>抽象类就可以变化实现不同的接口, 从而对实现类的影响就很小</p>
</blockquote>
<h1 id="过滤器模式"><a href="#过滤器模式" class="headerlink" title="过滤器模式"></a>过滤器模式</h1><p>过滤器模式（Filter Pattern）或标准模式（Criteria Pattern）是一种设计模式，这种模式允许开发人员使用不同的标准来过滤一组对象，通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式，它结合多个标准来获得单一标准。</p>
<blockquote>
<p>如果有一组对象, 需要经常根据不同条件过滤查询其中对象.  可以把这些过滤条件方法抽象成接口.   不同条件就是实现这个接口的不同实例,  只要把这组对象放入过滤实例中就可以过滤这个对象.  还可以灵活下使得不同过滤条件可以自由组合. </p>
</blockquote>
<h1 id="代理模式和装饰器模式"><a href="#代理模式和装饰器模式" class="headerlink" title="代理模式和装饰器模式"></a>代理模式和装饰器模式</h1><p>学习AOP时，教材上面都说使用的是动态代理，可是在印象中代理模式一直都是控制访问什么的，怎么又动态增加行为了，动态增加行为不是装饰器模式吗？于是 找了很多资料，想弄清楚这两者之间到底有什么区别。</p>
<p>​    这两个设计模式看起来很像。对装饰器模式来说，装饰者（decorator）和被装饰者（decoratee）都实现同一个 接口。对代理模式来说，代理类（proxy class）和真实处理的类（real class）都实现同一个接口。此外，不论我们使用哪一个模式，都可以很容易地在真实对象的方法前面或者后面加上自定义的方法。</p>
<p>​        然而，实际上，在装饰器模式和代理模式之间还是有很多差别的。装饰器模式关注于在一个对象上动态的添加方法，然而代理模式关注于控制对对象的访问。换句话 说，用代理模式，代理类（proxy class）可以对它的客户隐藏一个对象的具体信息。因此，当使用代理模式的时候，我们常常在一个代理类中创建一个对象的实例。并且，当我们使用装饰器模 式的时候，我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。</p>
<p>​        我们可以用另外一句话来总结这些差别：使用代理模式，代理和真实对象之间的的关系通常在编译时就已经确定了，而装饰者能够在运行时递归地被构造。    </p>
<p>Java的Stream 流的一系列接口就使用了装饰器模式,  外层的stream可以装饰传入的内层的stream</p>
<h2 id="组合模式定义"><a href="#组合模式定义" class="headerlink" title="组合模式定义"></a>组合模式定义</h2><p>组合模式（Composite Pattern）将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户可以使用一致的方法操作单个对象和组合对象。</p>
<blockquote>
<p>有点类似有层级结构的观察者模式. 可以对应使用与一对多的层级场景,  比如公司到部门,  部门到子部门</p>
</blockquote>
<p>####组合模式优缺点. </p>
<p>#####组合模式优点</p>
<ul>
<li>高层模块调用简单。组合模式中，用户不用关心到底是处理简单组件还是复合组件，可以按照统一的接口处理。不必判断组件类型，更不用为不同类型组件分开处理。</li>
<li>组合模式可以很容易的增加新的组件。若要增加一个简单组件或复合组件，只须找到它的父节点即可，非常容易扩展，符合“开放-关闭”原则。</li>
</ul>
<p>#####组合模式缺点</p>
<ul>
<li>无法限制组合组件中的子组件类型。在需要检测组件类型时，不能依靠编译期的类型约束来实现，必须在运行期间动态检测。</li>
</ul>
<h2 id="桥接模式-1"><a href="#桥接模式-1" class="headerlink" title="桥接模式:"></a>桥接模式:</h2><p>当一种事物可在多种维度变化（如两个维度，每个维度三种可能）时，如果为每一种可能创建一个子类，则每增加一个维度上的可能需要增加多个类，这会造成类爆炸（3*3=9）。若使用桥接模式，使用类聚合，而非继承，将可缓解类爆炸，并增强可扩展性。</p>
<blockquote>
<p>感觉桥接模式 的名称称呼改为组合模式更好,  但是组合模式已经是另外一个模式了.   所以称为聚合模式比较好,  总感觉设计模式的名称容易使人误导</p>
</blockquote>
<blockquote>
<p>获得依赖对象的实例的引用, 而不是使用继承, 这样就可以很好的解决多个维度类的爆炸增长问题.  父类的改变也不会影响引用类. 集成就会影响了</p>
</blockquote>
<h2 id="策略模式定义"><a href="#策略模式定义" class="headerlink" title="策略模式定义"></a>策略模式定义</h2><p>在策略模式（Strategy Pattern）中，一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。</p>
<p>在策略模式中，我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。</p>
<blockquote>
<p>需要调用策略(算法或者方法), 不直接掉用, 需要把具体的策略传入一个中间的策略调用类, 在使用策略调用类来调用具体的策略.   根据和装饰器模式和代理模式都有写相似.  策略模式可以结合工厂模式来一起使用,  工厂模式就很适合创建不同的策略</p>
</blockquote>
<p>#####策略模式优点</p>
<ul>
<li>策略模式提供了对“开闭原则”的完美支持，用户可以在不修改原有系统的基础上选择算法（策略），并且可以灵活地增加新的算法（策略）。</li>
<li>策略模式通过Context类提供了管理具体策略类（算法族）的办法。</li>
<li>结合简单工厂模式和Annotation，策略模式可以方便的在不修改客户端代码的前提下切换算法（策略）。</li>
</ul>
<p>#####策略模式缺点</p>
<ul>
<li>传统的策略模式实现方式中，客户端必须知道所有的具体策略类，并须自行显示决定使用哪一个策略类。但通过本文介绍的通过和Annotation和简单工厂模式结合，可以有效避免该问题</li>
<li>如果使用不当，策略模式可能创建很多具体策略类的实例，但可以通过使用上文《<a href="http://www.jasongj.com/design_pattern/flyweight/" target="_blank" rel="noopener">Java设计模式（十一） 享元模式</a>》介绍的享元模式有效减少对象的数量。</li>
</ul>
<h2 id="状态模式"><a href="#状态模式" class="headerlink" title="状态模式"></a>状态模式</h2><p>状态模式就是一个对象在不同的状态下 其行为的名称虽然一样, 但是行为不同.    </p>
<p>比如 使用某播放器看视频, </p>
<ul>
<li>在视频全屏状态下 按 Esc键是退出全屏,  按Enter键是暂停,   </li>
<li>在非全屏状态下, 按Esc键是最小化隐藏浏览器,  按enter是全屏</li>
</ul>
<p>在这个情况下, 用户进行了按键操作, 我们第一步先判断是什么状态,  在第二步判断是按的什么键. </p>
<p>使用if-else 模式会有很多的判断,  因为我举例子的状态只有两种, 但是还有可能又半屏状态, 有后台运行状态, 有永远置于最上面窗口的状态等等,   同时按键也有可能很多.  这样你需要的if判断就非常多了</p>
<p>这种情况就可以使用状态模式, 当播放器只持有一个当前状态类对象,  如果状态改变了, 就改变这个状态类对象. 用户按了什么键盘, 播放器不管, 播放器直接传给这个状态对象, 状态对象再在自己的内部处理这个按键事件</p>
<blockquote>
<p>这个例子就是提取出来易变化的部分, 状态和对应的按键事件封装成不同的对象去处理不同的各个事件, 当状态变化的时候只要改变下当前播放器的状态就可以处理对应的按键事件</p>
</blockquote>
<p>#####策略模式和状态模式: </p>
<blockquote>
<p>策略模式是需要调用方直接传递进来策略,  我执行传进来的策略就可以,   而而状态模式不同, 需要该局状态来执行不同的策略, 状态模式就是把状态和对应策略封装一起. 直接通过状态调用对应的策略就行了</p>
</blockquote>
<p>##责任链模式</p>
<p>顾名思义，责任链模式（Chain of Responsibility Pattern）为请求创建了一个接收者对象的链。这种模式给予请求的类型，对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。</p>
<p>在这种模式中，通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求，那么它会把相同的请求传给下一个接收者，依此类推。</p>
<blockquote>
<p>使用广泛,  netty的消息处理中就使用责任链模式,   spring中的拦截器,  servlet中的过滤器都是使用了这个模式</p>
</blockquote>
<h2 id="命令模式"><a href="#命令模式" class="headerlink" title="命令模式"></a>命令模式</h2><p>命令模式（Command Pattern）是一种数据驱动的设计模式，它属于行为型模式。请求以命令的形式包裹在对象中，并传给调用对象。调用对象寻找可以处理该命令的合适的对象，并把该命令传给相应的对象，该对象执行命令。</p>
<blockquote>
<p>与状态模式有点像,  就是把 一个调用拆分成三个,  分别是 调用者,  接收者,  和命令.   注意命令的接收者不要实现命令的执行.   命令的执行要封装到命令对象中, 接收者只是负责调用下命令对象中的执行方法</p>
<p>注意  命令不是pojo对象.  命令还包含操作方法. 如果我们过度的把数据和操作分离, 那么数据就是pojo, 操作就是业务类, 所以很多的业务类方法中需要判读pojo的类型, 再调用对应的if-else来执行逻辑, 这种方式是不好的. 可以使用命令模式来减少这种if判断.  但是可能会增加很多的命令类,  这个利弊问题需要在使用的时候考虑清楚</p>
</blockquote>
<p>在以下情况下可以使用命令模式：</p>
<ul>
<li>系统需要将请求调用者和请求接收者解耦，使得调用者和接收者不直接交互。</li>
<li>系统需要在不同的时间指定请求、将请求排队和执行请求。</li>
<li>系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。</li>
<li>系统需要将一组操作组合在一起，即支持宏命令</li>
</ul>
<h2 id="模板模式"><a href="#模板模式" class="headerlink" title="模板模式"></a>模板模式</h2><p>在模板模式（Template Pattern）中，一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现，但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。</p>
<blockquote>
<p>就是在一个类中把确定的方法实现, 不确定的方法使用虚拟方法代替.  然后不同的子类实现自己逻辑的虚拟方法, 这样就可以子类 就十分简洁只要实现易变化的方法就行</p>
<p>这个模式也是使用继承的特性, 不可避免的会有继承的缺点, 就是父类的改变导致所有子类会跟着改变</p>
</blockquote>
<h2 id="外观模式-门面模式"><a href="#外观模式-门面模式" class="headerlink" title="外观模式 (门面模式)"></a>外观模式 (门面模式)</h2><p>外观模式(Facade Pattern)：外部与一个子系统的通信必须通过一个统一的外观对象进行，为子系统中的一组接口提供一个一致的界面，外观模式定义了一个高层接口，这个接口使得这一子系统更加容易使用。外观模式又称为门面模式，它是一种对象结构型模式。</p>
<blockquote>
<p>外观模式 很类似与springcloud微服务中的zuul. 所有的http请求都通过zuul中转一下在到具体的微服务中去.  而zuul就是具体的外观对象.   这个模式可以降低系统之间调用的依赖性.  如果增加新的微服务, 需要增减zuul的映射关系(其实使用约定的规律可以不用修改映射关系) .   就是增减子系统, 需要修改对应的门面的类</p>
</blockquote>
<p>适配器模式是将一个不规范(无法调用)的接口封装成规范的接口. </p>
<p>而外观模式着重与提供统一的入口去调用不同的子系统</p>
<h2 id="观察者模式"><a href="#观察者模式" class="headerlink" title="观察者模式"></a>观察者模式</h2><p>建立一种对象与对象之间的依赖关系，一个对象发生改变时将自动通知其他对象，其他对象将相应做出反应。在此，发生改变的对象称为观察目标，而被通知的对象称为观察者，一个观察目标可以对应多个观察者，而且这些观察者之间没有相互联系，可以根据需要增加和删除观察者，使得系统更易于扩展，这就是观察者模式的模式动机。</p>
<blockquote>
<p>被观察者中需要维护(保存)着所有观察者的引用, 当目标(被观察者)发生变化, 需要维护的引用通知到每一个观察者. </p>
</blockquote>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/深入理解java虚拟机/" rel="tag"># 深入理解java虚拟机</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/01/22/docker/docker-compose部署springcloud踩的坑/" rel="next" title="docker-compose部署springcloud踩的坑">
                <i class="fa fa-chevron-left"></i> docker-compose部署springcloud踩的坑
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/01/28/centos安装nginx教程/" rel="prev" title="centos安装nginx">
                centos安装nginx <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">xiezc</p>
              <p class="site-description motion-element" itemprop="description">主要一些技术文章, 有些文章是转载的</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">72</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                
                  <span class="site-state-item-count">1</span>
                  <span class="site-state-item-name">分类</span>
                
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                
                  <span class="site-state-item-count">20</span>
                  <span class="site-state-item-name">标签</span>
                
              </div>
            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#二、设计模式的六大原则"><span class="nav-number">1.</span> <span class="nav-text">二、设计模式的六大原则</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#总原则：开闭原则（Open-Close-Principle）"><span class="nav-number">1.1.</span> <span class="nav-text">总原则：开闭原则（Open Close Principle）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1、单一职责原则"><span class="nav-number">1.2.</span> <span class="nav-text">1、单一职责原则</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2、里氏替换原则（Liskov-Substitution-Principle）"><span class="nav-number">1.3.</span> <span class="nav-text">2、里氏替换原则（Liskov Substitution Principle）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3、依赖倒转原则（Dependence-Inversion-Principle）"><span class="nav-number">1.4.</span> <span class="nav-text">3、依赖倒转原则（Dependence Inversion Principle）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4、接口隔离原则（Interface-Segregation-Principle）"><span class="nav-number">1.5.</span> <span class="nav-text">4、接口隔离原则（Interface Segregation Principle）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5、迪米特法则（最少知道原则）（Demeter-Principle）"><span class="nav-number">1.6.</span> <span class="nav-text">5、迪米特法则（最少知道原则）（Demeter Principle）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6、合成复用原则（Composite-Reuse-Principle）"><span class="nav-number">1.7.</span> <span class="nav-text">6、合成复用原则（Composite Reuse Principle）</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#该23种设计模式"><span class="nav-number">2.</span> <span class="nav-text">该23种设计模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#单例模式"><span class="nav-number">2.1.</span> <span class="nav-text">单例模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#工厂方法模式"><span class="nav-number">2.2.</span> <span class="nav-text">工厂方法模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#抽象工厂模式"><span class="nav-number">2.3.</span> <span class="nav-text">抽象工厂模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#建造者模式"><span class="nav-number">2.4.</span> <span class="nav-text">建造者模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#原型模式"><span class="nav-number">2.5.</span> <span class="nav-text">原型模式</span></a></li></ol></li></ol><li class="nav-item nav-level-1"><a class="nav-link" href="#适配器模式"><span class="nav-number"></span> <span class="nav-text">适配器模式</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#桥接模式"><span class="nav-number"></span> <span class="nav-text">桥接模式</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#过滤器模式"><span class="nav-number"></span> <span class="nav-text">过滤器模式</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#代理模式和装饰器模式"><span class="nav-number"></span> <span class="nav-text">代理模式和装饰器模式</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#组合模式定义"><span class="nav-number">1.</span> <span class="nav-text">组合模式定义</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#桥接模式-1"><span class="nav-number">2.</span> <span class="nav-text">桥接模式:</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#策略模式定义"><span class="nav-number">3.</span> <span class="nav-text">策略模式定义</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#状态模式"><span class="nav-number">4.</span> <span class="nav-text">状态模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#命令模式"><span class="nav-number">5.</span> <span class="nav-text">命令模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#模板模式"><span class="nav-number">6.</span> <span class="nav-text">模板模式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#外观模式-门面模式"><span class="nav-number">7.</span> <span class="nav-text">外观模式 (门面模式)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#观察者模式"><span class="nav-number">8.</span> <span class="nav-text">观察者模式</span></a></li></ol></li></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">xiezc</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  
  <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js"></script>
  <script>AV.initialize("eRAHvO0xVYwckgdXIVpfugRG-gzGzoHsz", "57lKp708hde92YeG1xX9MQj1");</script>
  <script>
    function showTime(Counter) {
      var query = new AV.Query(Counter);
      var entries = [];
      var $visitors = $(".leancloud_visitors");

      $visitors.each(function () {
        entries.push( $(this).attr("id").trim() );
      });

      query.containedIn('url', entries);
      query.find()
        .done(function (results) {
          var COUNT_CONTAINER_REF = '.leancloud-visitors-count';

          if (results.length === 0) {
            $visitors.find(COUNT_CONTAINER_REF).text(0);
            return;
          }

          for (var i = 0; i < results.length; i++) {
            var item = results[i];
            var url = item.get('url');
            var time = item.get('time');
            var element = document.getElementById(url);

            $(element).find(COUNT_CONTAINER_REF).text(time);
          }
          for(var i = 0; i < entries.length; i++) {
            var url = entries[i];
            var element = document.getElementById(url);
            var countSpan = $(element).find(COUNT_CONTAINER_REF);
            if( countSpan.text() == '') {
              countSpan.text(0);
            }
          }
        })
        .fail(function (object, error) {
          console.log("Error: " + error.code + " " + error.message);
        });
    }

    function addCount(Counter) {
      var $visitors = $(".leancloud_visitors");
      var url = $visitors.attr('id').trim();
      var title = $visitors.attr('data-flag-title').trim();
      var query = new AV.Query(Counter);

      query.equalTo("url", url);
      query.find({
        success: function(results) {
          if (results.length > 0) {
            var counter = results[0];
            counter.fetchWhenSave(true);
            counter.increment("time");
            counter.save(null, {
              success: function(counter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(counter.get('time'));
              },
              error: function(counter, error) {
                console.log('Failed to save Visitor num, with error message: ' + error.message);
              }
            });
          } else {
            var newcounter = new Counter();
            /* Set ACL */
            var acl = new AV.ACL();
            acl.setPublicReadAccess(true);
            acl.setPublicWriteAccess(true);
            newcounter.setACL(acl);
            /* End Set ACL */
            newcounter.set("title", title);
            newcounter.set("url", url);
            newcounter.set("time", 1);
            newcounter.save(null, {
              success: function(newcounter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(newcounter.get('time'));
              },
              error: function(newcounter, error) {
                console.log('Failed to create');
              }
            });
          }
        },
        error: function(error) {
          console.log('Error:' + error.code + " " + error.message);
        }
      });
    }

    $(function() {
      var Counter = AV.Object.extend("Counter");
      if ($('.leancloud_visitors').length == 1) {
        addCount(Counter);
      } else if ($('.post-title-link').length > 1) {
        showTime(Counter);
      }
    });
  </script>



  

  
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>


  
  

  

  

  

</body>
</html>
